package com.lemonPiggy.UDForm.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lemonPiggy.UDForm.domain.UDFormWebPage;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.result.UpdateResult;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.IdUtils;
import com.ruoyi.common.core.utils.SecurityUtils;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.system.api.RemoteActivitiService;
import com.ruoyi.system.api.domain.ActKeyPage;
import com.lemonPiggy.UDForm.service.IUDFormWebPageService;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;


/**
 * 表单值Controller
 *
 * @author cheng
 * @create 2021-08-05-12:36
 */
@RestController
@RequestMapping("/pageValue")
public class UDFormPageValueController {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RemoteActivitiService remoteActivitiService;
    @Autowired
    private IUDFormWebPageService UDFormWebPageService;

    /**
     * 新增表单值
     *
     * @param inmap 取得表名table
     *              inmap中有个map来存放数据
     * @return
     */
    @PostMapping
    public R add(@RequestBody Map inmap) {
        //取到表名key的值，赋予table
        String table = inmap.get("table").toString();
        //inmap中又嵌套了一个map，来插入。
        Map map = (Map) inmap.get("map");
        String uuid = IdUtils.simpleUUID();
        map.put("_id", uuid);
        map.put("created_by", SecurityUtils.getUsername());
        map.put("created_time", new Date());
        map.put("updated_by", SecurityUtils.getUsername());
        map.put("updated_time", new Date());
        map.put("instance_id", "");
        map.put("process_key", "");
        return R.ok(mongoTemplate.insert(map, table));
    }

    /**
     * 修改表单值
     *
     * @param inmap 将inmap解析 取得数据的id和 table表名
     *              取得map 通过map来修改数据内容
     * @return
     */
    @PutMapping
    public R edit(@RequestBody Map inmap) {
        String id = inmap.get("id").toString();
        String table = inmap.get("table").toString();
        Map<String, Object> map = (Map) inmap.get("map");
        Query query = new Query(Criteria.where("_id").is(id));
        Update update = new Update();
        for (String key : map.keySet()) {//keySet获取map集合key的集合  然后在遍历key即可
            Object value = map.get(key);
            //把map的key，和遍历出来的value 通过update然后set进去，可以修改表的字段值了。
            update.set(key, value);
        }
        update.set("updated_by", SecurityUtils.getUsername());
        update.set("updated_time", new Date());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, table);
        if (updateResult != null) {
            if (updateResult.getMatchedCount() > 0) {
                return R.ok(updateResult);
            }
        }
        return R.fail(updateResult);
    }

    /**
     * 提交申请
     *
     * @param inmap 将inmap解析 取得数据的id和 table表名
     *              取得map 通过map来修改数据内容
     * @return
     */
    @PutMapping("/submitApply")
    public R submitApply(@RequestBody Map inmap) {
        String id = inmap.get("id").toString();
        String table = inmap.get("table").toString();
        Map<String, Object> map = (Map) inmap.get("map");
        Query query = new Query(Criteria.where("_id").is(id));
        Update update = new Update();
        for (String key : map.keySet()) {//keySet获取map集合key的集合  然后在遍历key即可
            String value = map.get(key).toString();
            //把map的key，和遍历出来的value 通过update然后set进去，可以修改表的字段值了。
            update.set(key, value);
        }
        update.set("updated_by", SecurityUtils.getUsername());
        update.set("updated_time", new Date());
        ActKeyPage akp = new ActKeyPage();
        akp.setPageId(table);
        if (remoteActivitiService.listNoPaging(akp).getData().size() == 0) {
            R.fail("没有绑定工作流");
        }
        ActKeyPage reakp = remoteActivitiService.listNoPaging(akp).getData().get(0);
        if (null != reakp) {
            Map<String, Object> keymap = new HashMap<>();
            keymap.put("entity", map);
            keymap.put("key", reakp.getActivitiKey());
            keymap.put("table", table);
            //processService.submitApply(bizLeave, "leave");方法重写
            Map<String, Object> remap = remoteActivitiService.submitApplyByMap(keymap).getData();
            update.set("instance_id", remap.get("instance_id"));
            update.set("process_key", reakp.getActivitiKey());
        }

        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, table);
        if (updateResult != null) {
            if (updateResult.getMatchedCount() > 0) {
                return R.ok(updateResult);
            }
        }
        return R.fail(updateResult);
    }

    /**
     * 获取表单值详细信息
     *
     * @param id    查询的id
     * @param table 查询的表
     *              查询到对应的表名再查询相对应的id信息
     * @return
     */
    //根据id来查询
    @GetMapping("/find")
    //postman地址上要加上id和table表名
    public R<Map<String, Object>> findById(String id, String table) {
        Map<String, Object> object = mongoTemplate.findById(id, Map.class, table);
        return R.ok(object);
    }


    /**
     * 查询所有表单值，根据条件来查询表单值
     *
     * @param inmap 将 map解析 取得pageNum和pageSize
     *              取得table 表名
     * @return
     */
    @PostMapping("/findAll")
    public TableDataInfo findAll(@RequestBody Map inmap) {
        Integer pageNum = 0;
        Integer pageSize = 10;
        if (inmap.get("pageNum") != null) {
            pageNum = Integer.valueOf(inmap.get("pageNum") + "") - 1;
        }
        if (inmap.get("pageSize") != null) {
            pageSize = Integer.valueOf(inmap.get("pageSize") + "");
        }
        Pageable pageable = PageRequest.of(pageNum, pageSize);
        //取到表名key的值，赋予table
        String table = inmap.get("table").toString();
        //inmap中又嵌套了一个map，来插入。
        Map<String, Object> map = (Map) inmap.get("map");
        List<Map> all = mongoTemplate.findAll(Map.class, table);
        //================表关联判断===========================================================================
        UDFormWebPage UDFormWebPage = UDFormWebPageService.selectUDFormWebPageById(table);
        String relationShip = UDFormWebPage.getRelationShip();
        List<Map> list = new ArrayList<>();
        String page="";
        JSONArray fieldList=new JSONArray();
        if (relationShip != null) {
            JSONObject jsonObject = JSON.parseObject(relationShip);
            page = jsonObject.getString("page");
//            MongoCollection collection = mongoTemplate.getCollection(table);
//            List<Bson> agg = new ArrayList<>();
//            agg.add(Aggregates.lookup(page, "content", "name", "course"));
//            AggregateIterable<Map> aggregate = collection.aggregate(agg);
//            for (Map document : aggregate) {
//                list.add(document);
//            }
            fieldList = JSON.parseArray(jsonObject.getString("fieldList"));
            System.out.println(fieldList+"---------------");
        }
        if(null!=fieldList&&fieldList.size()>0){
            JSONObject fieldObject= (JSONObject) fieldList.get(0);//暂时制作单字段关联
            String localField="";
            String foreignField="";
            for (String key : fieldObject.keySet()) {
                String value = fieldObject.get(key).toString();
                localField=key;
                foreignField=value;
            }
            LookupOperation courseLookupOperation = LookupOperation.newLookup().
                    from(page).
                    localField(localField).
                    foreignField(foreignField).
                    as("course");
            UnwindOperation unwind = Aggregation.unwind("course");
            //将以上的条件封装
            List<AggregationOperation> operations = new ArrayList<>();
            operations.add(courseLookupOperation);
            if (map.size() > 0) {
                for (String key : map.keySet()) {
                    String value = map.get(key).toString();
                    AggregationOperation match = Aggregation.match(Criteria.where(key).is(value).regex(value));
                    operations.add(match);
                }
            }
            operations.add(Aggregation.skip(pageNum*pageSize));
            operations.add(Aggregation.limit(pageSize));
            Aggregation aggregation = Aggregation.newAggregation(operations);
            AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, table, Map.class);

            list = results.getMappedResults();
//========================================================================================================
        }else{
            Query query = new Query();
            if (map.size() > 0) {
                for (String key : map.keySet()) {
                    String value = map.get(key).toString();
                    query.addCriteria(Criteria.where(key).is(value).regex(value));
                }
            }
            query.with(pageable).with(Sort.by(Sort.Direction.DESC, "updated_time"));
            list = mongoTemplate.find(query, Map.class, table);
        }
        List<Map> newmaps = new ArrayList<Map>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(item -> {
                //组装关联表数据
                if(null!=item.get("course")){
                    List<Map<String,Object>> courseList=(List<Map<String,Object>>)item.get("course");
                    for(int i=0;i<courseList.size();i++){
                        Map<String,Object> course=courseList.get(i);
                        for(String key:course.keySet()){
                            if(!key.equals("created_by")&&!key.equals("created_time")&&!key.equals("process_key")&&
                                    !key.equals("updated_by")&&!key.equals("updated_time")&&!key.equals("_id")){
                                String value = course.get(key).toString();
                                item.put(key,value);
                            }
                        }
                        if(i!=courseList.size()-1){//多条关联数据，clone一条数据
                            newmaps.add(item);
                        }
                    }
                }
                //=====================
                if (null != item.get("instance_id") && !item.get("instance_id").equals("")) {
                    try {
                        newmaps.add((Map) remoteActivitiService.richProcessFieldByMap(item).getData());//填充流程相关字段
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    item.put("taskName", "未启动");
                    newmaps.add(item);
                }
            });
        }
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setRows(newmaps);
        rspData.setMsg("查询成功");
        rspData.setTotal(all.size());
        return rspData;
    }

    /**
     * 多选删除
     * @param inmap
     * @return
     */
    @DeleteMapping("/delete")
    public R deleteAll(@RequestBody Map inmap) {
        String id = inmap.get("id").toString().substring(1, inmap.get("id").toString().length() - 1);
        String[] ids = id.split(",");
        String table = inmap.get("table").toString();
        for (int i = 0; i < ids.length; i++) {
            deleteOne(ids[i], table);
        }
        return R.ok();
    }

    public int deleteOne(String id, String table) {
        Query query = new Query(Criteria.where("_id").is(id.trim()));
        long deletedCount = mongoTemplate.remove(query, table).getDeletedCount();
        return (int) deletedCount;
    }
    //表关联之间获取两个表中mongo里面的数据
    @GetMapping("/relationShip/{id}")
    public R findRelationShip(@PathVariable("id") String id){
        UDFormWebPage UDFormWebPage = UDFormWebPageService.selectUDFormWebPageById(id);
        String relationShip = UDFormWebPage.getRelationShip();
        if (relationShip==null){
            return R.fail("没有关系");
        }else {
            JSONObject jsonObject = JSON.parseObject(relationShip);
            String page = jsonObject.getString("page");
            UDFormWebPage UDFormWebPage1 = UDFormWebPageService.selectUDFormWebPageById(page);
            MongoCollection<Document> collection = mongoTemplate.getCollection(id);
            List<Bson> agg = new ArrayList<>();
            agg.add(Aggregates.lookup(page,"id","id","result"));
//            agg.add(Aggregates.match(Filters.ne("result",new ArrayList<String>(0))));
            AggregateIterable<Document> aggregate = collection.aggregate(agg);
            List<String> list = new ArrayList<>();
            for (Document document : aggregate) {
                list.add(document.toJson());
            }
            return R.ok(list);
        }
    }

}